package ityc.connection.serverHandler;

import com.alibaba.fastjson.JSONObject;
import com.sun.jmx.remote.internal.ArrayQueue;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.util.CharsetUtil;
import io.netty.channel.ChannelHandler.Sharable;
import ityc.connection.superPromise.SuperPromise;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {

    private static ChannelHandlerContext channelHandlerContext;

    private static SuperPromise superPromise = new SuperPromise();

    private static Map<String, Object> results = new HashMap<>();

    private ByteBuf buf = Unpooled.buffer();

    public static synchronized Object sendMessage(Map<String, Object> params, FullHttpRequest fullHttpRequest) throws InterruptedException {
        if (channelHandlerContext == null) {
            return null;
        }
        String key = UUID.randomUUID().toString();
        superPromise.createPromise(key, channelHandlerContext.newPromise());
        Map<String, Object> requestMap = new HashMap<>();
        List<Map.Entry<CharSequence, CharSequence>> entries = fullHttpRequest.headers().entries();
        for (Map.Entry<CharSequence, CharSequence> entry : entries) {
            requestMap.put(entry.getKey().toString(), entry.getValue());
        }

        requestMap.put("uri", fullHttpRequest.uri());
        requestMap.put("method", fullHttpRequest.method().toString());
        requestMap.put("params", params);
        requestMap.put("headerid", key);


        System.out.println("start sending content");
        String requestParams = JSONObject.toJSON(requestMap).toString();
        String ret = requestParams.length() + requestParams;
        channelHandlerContext.writeAndFlush(Unpooled.copiedBuffer(ret, CharsetUtil.UTF_8)).addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()) {
                    System.out.println("tcp 数据 发送成功" + ret);
                    System.out.println("数据长度:" + requestParams.length());
                } else {
                    Throwable throwable = channelFuture.cause();
                    throwable.printStackTrace();
                }
            }
        });
        System.out.println("sending content end");
        superPromise.await(key);
        return results.get(key);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        channelHandlerContext = ctx;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf tempBuf = (ByteBuf) msg;
        if (tempBuf.toString(CharsetUtil.UTF_8).equals("heartbeat")) {
            ctx.writeAndFlush(Unpooled.copiedBuffer("heartbeat", CharsetUtil.UTF_8));
            return;
        }
        buf.writeBytes(tempBuf);
        System.out.println("接收到返回的内容了" + buf.toString(CharsetUtil.UTF_8));
        String[] split = buf.toString(CharsetUtil.UTF_8).split("\\{");
        int dataLength = Integer.parseInt(split[0]);
        if (buf.readableBytes() - split[0].length() >= dataLength) {
            System.out.println("接收到的数据长度:" + (buf.readableBytes() - split[0].length()));
            Map<String, Object> resMsg = JSONObject.parseObject(buf.toString(CharsetUtil.UTF_8).substring(split[0].length()));
            if (resMsg.get("headerid") == null) throw new RuntimeException("please set headerId to the request header");
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(resMsg.get("result").toString(), CharsetUtil.UTF_8));
            for (String s : resMsg.keySet()) {
                if (!s.equals("result")) {
                    response.headers().add(s, resMsg.get(s).toString());
                }
            }
            buf = Unpooled.buffer();
            String headerId = resMsg.get("headerid").toString();
            results.put(headerId, response);
            superPromise.setSuccess(headerId);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}